/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.bean;

import org.ipti.br.tag.bo.WorkBO;
import org.ipti.br.tag.dao.DisciplineFacade;
import org.ipti.br.tag.dao.OrganizationFacade;
import org.ipti.br.tag.entity.Discipline;
import org.ipti.br.tag.entity.Organization;
import org.ipti.br.tag.entity.Work;
import org.ipti.br.tag.entity.WorkTopic;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.ipti.br.tag.pdf.WorkTopicsPDF;
import org.ipti.br.tag.util.LoggerUtil;

/**
 *
 * @author ipti
 */
@ManagedBean
@ViewScoped
public class WorkMB extends AppBaseBean implements Serializable {

    @Inject
    private WorkBO workBO;
    
    @Inject
    private DisciplineFacade disciplineDAO;
    
    @Inject
    private OrganizationFacade orgDAO;
    
    private WorkTopic topic;
    private Work work;
    
    private Discipline discipline;
    private Organization organization;
    private int workYear, manageYear;
    
    private TreeNode root;
    private TreeNode nodeSelected;
    
    public WorkMB() {
        workYear = this.getActualYear();
        manageYear = workYear;
    }
    
    public void prepareNode() {
        topic = new WorkTopic();
    }
    
    public void createNote() {
        try{
            topic.setFather((WorkTopic) nodeSelected.getData());
            workBO.createTopic(topic, workYear);
            
            new DefaultTreeNode(topic, nodeSelected);
            
            topic = null;
            addInfoMessage(":editWorksForm:message", "Sucesso", "Subtópico criado");
        }catch(Exception e){
            addErrorMessage(":editWorksForm:message", "Erro!", "Não foi possível criar o subtópico, tente novamente");
            LoggerUtil.log("createNote", Level.SEVERE, "Erro ao criar nó" + topic.getName(), e);
            topic = null;
        }
    }
    
    public void createSuperNode() {
        try {
            workBO.createWork(topic, organization, discipline, workYear);
            
            new DefaultTreeNode(topic, root);
            
            topic = null;
            addInfoMessage(":editWorksForm:message", "Sucesso", "Tópico criado");
        } catch(Exception e) {
            topic = null;
            addErrorMessage(":editWorksForm:message", "Erro!", "Não foi possível criar o tópico, tente novamente");
            LoggerUtil.log("createNote", Level.SEVERE, "Erro ao criar nó" + topic.getName(), e);
        }
    }
    
    public void renameNode(){
        WorkTopic wt = (WorkTopic) nodeSelected.getData();
        if (wt.getId() == null) {
            addErrorMessage(":editWorksForm:message", "Falha ao renomear", "Não é possível renomear este tópico");
        } else if(wt.getFinalDate() != null) {
            addErrorMessage(":editWorksForm:message", "Falha ao renomear", "Este tópico já foi renomeado nessa faixa de tempo");
        } else if(wt.getInitialDate().get(Calendar.YEAR) > workYear) {
            addErrorMessage(":editWorksForm:message", "Falha ao renomear", "Ano escolhido é anterior ao ano de implantação do tópico");
        } else {
            try{
                workBO.renameTopic(wt, workYear);
                addInfoMessage(":editWorksForm:message", "Sucesso", "Tópico renomeado");
            } catch(Exception e) {
                addErrorMessage(":editWorksForm:message", "Erro!", "Não foi possível renomear o tópico, tente novamente");
                LoggerUtil.log("createNote", Level.SEVERE, "Erro ao renomear nó" + wt.getName(), e);
            }
        }
    }
    
    public void disableNode() {
        WorkTopic wt = (WorkTopic) nodeSelected.getData();
        if (wt.getId() == null) {
            addErrorMessage(":editWorksForm:message", "Falha ao desabilitar", "Não é possível desabilitar este tópico");
        } else if(wt.getFinalDate() != null) {
            addErrorMessage(":editWorksForm:message", "Falha ao desabilitar", "Este tópico já foi desabilitado");
        } else if(wt.getInitialDate().get(Calendar.YEAR) > workYear) {
            addErrorMessage(":editWorksForm:message", "Falha ao desabilitar", "Ano escolhido é antecede o ano de implantação do tópico");
        } else {
            try {
                workBO.disableTopic(wt, workYear);
                addInfoMessage(":editWorksForm:message", "Sucesso", "Tópico desabilitardo a partir de "+workYear);
            } catch(Exception e) {
                addErrorMessage(":editWorksForm:message", "Erro!", "Não foi possível excluir o tópico, tente novamente");
                LoggerUtil.log("createNote", Level.SEVERE, "Erro ao excluir nó" + wt.getName(), e);
            }
        }
    }
    
    public void deleteNode() {
        WorkTopic wt = (WorkTopic) nodeSelected.getData();
        if (!workBO.canRemove(wt)) {
            addErrorMessage(":editWorksForm:message", "Falha ao excluir", "Não é possível remover este tópico");
        } else {
            workBO.deleteTopic(wt);
            nodeSelected.getParent().getChildren().remove(nodeSelected);
            addInfoMessage(":editWorksForm:message", "Tópico removido com sucesso", ":)");
        }
    }
    
    public void clear(){
        topic = null;
    }
    
    public void loadNodes() {
        if(discipline != null && organization != null){
            root = new DefaultTreeNode("Root", null);
            for (Work w : workBO.listWorks(workYear, organization, discipline)) {
                generateNodes(root, w.getTopic());
            }
        }
    }
    
    public void generatePDF() {
        ArrayList<WorkTopic> topics = new ArrayList<WorkTopic>();
        for (Work w : workBO.listWorks(workYear, organization, discipline)) {
            topics.add(w.getTopic());
        }
        new WorkTopicsPDF().generate(getFacesContext(),topics, organization, discipline);
    }
    
    public void generateCodes(){
        workBO.generateCodes(organization);
    }
    
    private void generateNodes(TreeNode node, WorkTopic topic) {
        TreeNode nodeSon = new DefaultTreeNode(topic, node);
        nodeSon.setExpanded(true);
        
        if(topic.getSons() != null || !topic.getSons().isEmpty()){
            WorkTopic wt;
            for (WorkTopic workTopic : workBO.getPrimary(topic).getSons()){
                wt = workBO.validateTopic(workTopic, workYear);
                if(wt != null){
                    generateNodes(nodeSon, wt);
                }
            }
        }
    }
    
    public boolean canRemove(){
        if(nodeSelected != null && nodeSelected.getData() != null) {
            return workBO.canRemove((WorkTopic) nodeSelected.getData());
        }
        
        return false;
    }
    
    public List<Discipline> getDisciplinePerOrganization(){
        return disciplineDAO.findAllOrder();
    }
    
    public List<Organization> getOrganizations(){
        List<Organization> orgs = orgDAO.getOrganizationChildren(orgDAO.getOrganizationByName("Fundamental Menor").getId());
        orgs.addAll(orgDAO.getOrganizationChildren(orgDAO.getOrganizationByName("Fundamental Maior").getId()));
        orgs.addAll(orgDAO.getOrganizationChildren(orgDAO.getOrganizationByName("Educação Infantil").getId()));
        return orgs;
    }

    public Discipline getDiscipline() {
        return discipline;
    }

    public void setDiscipline(Discipline discipline) {
        this.discipline = discipline;
    }

    public TreeNode getNodeSelected() {
        return nodeSelected;
    }

    public void setNodeSelected(TreeNode nodeSelected) {
        this.nodeSelected = nodeSelected;
    }

    public Organization getOrganization() {
        return organization;
    }

    public void setOrganization(Organization organization) {
        this.organization = organization;
    }

    public TreeNode getRoot() {
        return root;
    }

    public void setRoot(TreeNode root) {
        this.root = root;
    }

    public WorkTopic getTopic() {
        return topic;
    }

    public void setTopic(WorkTopic topic) {
        this.topic = topic;
    }

    public Work getWork() {
        return work;
    }

    public void setWork(Work work) {
        this.work = work;
    }

    public WorkBO getWorkBO() {
        return workBO;
    }

    public void setWorkBO(WorkBO workBO) {
        this.workBO = workBO;
    }

    public int getWorkYear() {
        return workYear;
    }

    public void setWorkYear(int workYear) {
        this.workYear = workYear;
    }

    public int getManageYear() {
        return manageYear;
    }

    public void setManageYear(int manageYear) {
        this.manageYear = manageYear;
    }

    public DisciplineFacade getDisciplineDAO() {
        return disciplineDAO;
    }

    public void setDisciplineDAO(DisciplineFacade disciplineDAO) {
        this.disciplineDAO = disciplineDAO;
    }

    public OrganizationFacade getOrgDAO() {
        return orgDAO;
    }

    public void setOrgDAO(OrganizationFacade orgDAO) {
        this.orgDAO = orgDAO;
    }
    
}
